﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NigiriClub.WebUI.Models;
using System.Web.Security;
using Microsoft.Web.WebPages.OAuth;
using DotNetOpenAuth.AspNet;
using WebMatrix.WebData;
using NigiriClub.WebUI.Filters;

namespace NigiriClub.WebUI.Controllers
{
  [InitializeSimpleMembership]
  public class AccountController : Controller
  {
    [AllowAnonymous]
    [ChildActionOnly]
    public ActionResult LoginsList()
    {
      return PartialView("_LoginsListPartial", OAuthWebSecurity.RegisteredClientData);
    }

    [AllowAnonymous]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {
      return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
    }

    internal class ExternalLoginResult : ActionResult
    {
      public ExternalLoginResult(string provider, string returnUrl)
      {
        Provider = provider;
        ReturnUrl = returnUrl;
      }

      public string Provider { get; private set; }
      public string ReturnUrl { get; private set; }

      public override void ExecuteResult(ControllerContext context)
      {
        OAuthWebSecurity.RequestAuthentication(Provider, ReturnUrl);
      }
    }

    [AllowAnonymous]
    public ActionResult ExternalLoginCallback()
    {
      AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback"));
      if (!result.IsSuccessful)
      {
        return RedirectToAction("ExternalLoginFailure");
      }

      if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
      {
        return RedirectToAction("Index", "Home");
      }

      if (User.Identity.IsAuthenticated)
      {
        // If the current user is logged in add the new account
        OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
        return RedirectToAction("Index", "Home");
      }
      else
      {
        // User is new, ask for their desired membership name
        string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
        ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
        return View("ExternalLoginConfirmation",
          new Account
          {
            FullName = result.UserName,
            Name = result.UserName,
            ExternalLoginData = loginData,
            PermissionId = 1
          });
      }
    }

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLoginConfirmation(Account model)
    {
      string provider = null;
      string providerUserId = null;

      if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
      {
        return RedirectToAction("Manage");
      }

      if (ModelState.IsValid)
      {
        // Insert a new user into the database
        using (Entities db = new Entities())
        {
          Account user = db.Account.FirstOrDefault(u => u.Name == model.Name);
          // Check if user already exists
          if (user == null)
          {
            // TODO: fix permission
            db.Account.Add(model);
            db.SaveChanges();

            OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.Name);
            OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);

            return RedirectToAction("Index", "Home");
          }
          else
          {
            ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
          }
        }
      }

      ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
      //ViewBag.ReturnUrl = returnUrl;
      return View(model.Clone());
    }

    //
    // GET: /Account/ExternalLoginFailure

    [AllowAnonymous]
    public ActionResult ExternalLoginFailure()
    {
      return View();
    }

    public ActionResult Logout()
    {
      WebSecurity.Logout();

      return RedirectToAction("Index", "Home");
    }
  }
}
